import {NgModule,Component,ElementRef,AfterViewInit,DoCheck,OnDestroy,Input,Output,ViewChild,EventEmitter,IterableDiffers,Optional} from '@angular/core';
import {CommonModule} from '@angular/common';
import {Message} from '../common/message';
import {DomHandler} from '../dom/domhandler';
import {MessageService} from '../common/messageservice';
import {Subscription}   from 'rxjs/Subscription';

@Component({
    selector: 'p-growl',
    styles:[`.bg-00d11d{background:#00d11d} .bg-ff0000{background:#ff0000} .bg-ffc000{background:#ffc000} .text-stroke{-webkit-text-stroke: 3px} 
        .text-stroke-ffc000{-webkit-text-stroke-color: #ffc000} .text-stroke-ff0000{-webkit-text-stroke-color: #ff0000} .text-stroke-00d11d{-webkit-text-stroke-color: #00d11d}
    `],
    template: `
        <div #container style="width: max-content;" [ngClass]="'ui-growl ui-widget text-center'" [ngStyle]="style" [class]="styleClass">
            <div #msgel style="background:rgba(0,0,0,.7) !important" *ngFor="let msg of value;let i = index" class="ui-growl-item-container ui-state-highlight ui-corner-all ui-shadow" aria-live="polite"
                [ngClass]="{'ui-growl-message-info':msg.severity == 'info','ui-growl-message-warn':msg.severity == 'warn',
                    'ui-growl-message-error':msg.severity == 'error','ui-growl-message-success':msg.severity == 'success'}"
                    (click)="onMessageClick(i)" (mouseenter)="onMessageHover(i)">
                <div class="ui-growl-item" style="padding:38px 30px">
                     <div class="ui-growl-icon-close fa fa-close" *ngIf="showClose"  (click)="remove(i,msgel)"></div>
                     <span class="fa text-stroke" style="border-radius: 50%;font-size:24px;vertical-align: middle;width: 32px;height: 32px;text-align: center;line-height: 32px;"
                        [ngClass]="{'fa-info-circle':msg.severity == 'info','fa-exclamation bg-ffc000 text-stroke-ffc000':msg.severity == 'warn',
                                'fa-close bg-ff0000 text-stroke-ff0000':msg.severity == 'error','fa-check bg-00d11d text-stroke-00d11d':msg.severity == 'success'}"></span>
                     <span class="m-l-10">
                        <span class="ui-growl-title" *ngIf="msg.summary">{{msg.summary}}</span>
                        <span [innerHTML]="msg.detail"></span>
                     </span>
                     <div style="clear: both;"></div>
                </div>
            </div>
        </div>
    `,
    providers: [DomHandler]
})
export class Growl implements AfterViewInit,DoCheck,OnDestroy {

    @Input() showClose:boolean = false;

    @Input() sticky: boolean;

    @Input() life: number = 1500;
        
    @Input() style: any;
        
    @Input() styleClass: string;
    
    @Input() immutable: boolean = true;
    
    @Input() autoZIndex: boolean = true;
    
    @Input() baseZIndex: number = 0;
    
    @Output() onClick: EventEmitter<any> = new EventEmitter();
    
    @Output() onHover: EventEmitter<any> = new EventEmitter();
    
    @Output() onClose: EventEmitter<any> = new EventEmitter();
    
    @Output() valueChange: EventEmitter<Message[]> = new EventEmitter<Message[]>();
    
    @ViewChild('container') containerViewChild: ElementRef;
    
    _value: Message[];
                        
    timeout: any;
    
    preventRerender: boolean;
    
    differ: any;
    
    subscription: Subscription;
    
    closeIconClick: boolean;
        
    constructor(public el: ElementRef, public domHandler: DomHandler, public differs: IterableDiffers, @Optional() public messageService: MessageService) {
        this.differ = differs.find([]).create(null);
        
        if(messageService) {
            this.subscription = messageService.messageObserver.subscribe(messages => {
                if(messages) {
                    if(messages instanceof Array)
                        this.value = this.value ? [...this.value, ...messages] : [...messages];
                    else
                        this.value = this.value ? [...this.value, ...[messages]]: [messages];
                }
                else {
                    this.value = null;
                }
            });
        }
    }

    ngAfterViewInit() {
        if(!this.sticky) {
            this.initTimeout();
        }
    }
    
    @Input() get value(): Message[] {
        return this._value;
    }

    set value(val:Message[]) {
        this._value = val;
        if(this.containerViewChild && this.containerViewChild.nativeElement && this.immutable) {
            this.handleValueChange();
        }
    }
    
    ngDoCheck() {
        if(!this.immutable && this.containerViewChild && this.containerViewChild.nativeElement) {
            let changes = this.differ.diff(this.value);
            if(changes) {
                this.handleValueChange();
            }
        }
    }
    
    handleValueChange() {
        if(this.preventRerender) {
            this.preventRerender = false;
            return;
        }
        
        if(this.autoZIndex) {
            this.containerViewChild.nativeElement.style.zIndex = String(this.baseZIndex + (++DomHandler.zindex));
        }
        this.domHandler.fadeIn(this.containerViewChild.nativeElement, 250);
        
        if(!this.sticky) {
            this.initTimeout();
        }
    }
    
    initTimeout() {
        if(this.timeout) {
            clearTimeout(this.timeout);
        }
        this.timeout = setTimeout(() => {
            this.removeAll();
        }, this.life);
    }
        
    remove(index: number, msgel: any) {      
        this.closeIconClick = true;  
        this.domHandler.fadeOut(msgel, 250);
        
        setTimeout(() => {
            this.preventRerender = true;
            this.onClose.emit({message:this.value[index]});
            
            if(this.immutable) {
                this._value = this.value.filter((val,i) => i!=index);
                this.valueChange.emit(this._value);
            }
            else {
                this._value.splice(index, 1);
            }
        }, 250);        
    }
    
    removeAll() {
        if(this.value && this.value.length) {            
            this.domHandler.fadeOut(this.containerViewChild.nativeElement, 250);
            
            setTimeout(() => {                
                this.value.forEach((msg,index) => this.onClose.emit({message:this.value[index]}));
                if(this.immutable) {
                    this.value = [];
                    this.valueChange.emit(this.value);
                }
                else {
                    this.value.splice(0, this.value.length);
                }
            }, 250);
        }
    }
    
    onMessageClick(i: number) {
        if(this.closeIconClick)
            this.closeIconClick = false;
        else
            this.onClick.emit({message: this.value[i]});
    }
    
    onMessageHover(i: number) {
        this.onHover.emit({message: this.value[i]});
    }
    
    ngOnDestroy() {
        if(!this.sticky) {
            clearTimeout(this.timeout);
        }
        
        if(this.subscription) {
            this.subscription.unsubscribe();
        }
    }

}

@NgModule({
    imports: [CommonModule],
    exports: [Growl],
    declarations: [Growl]
})
export class GrowlModule { }